package xyz.molzhao.alink.service.aliyunoss;

import cn.hutool.core.text.CharSequenceUtil;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.StorageClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import xyz.molzhao.alink.base.ResultEnum;
import xyz.molzhao.alink.constants.CommonConstant;
import xyz.molzhao.alink.domain.StorageContext;
import xyz.molzhao.alink.enums.StorageClientEnum;
import xyz.molzhao.alink.exception.BusinessException;
import xyz.molzhao.alink.properties.StorageClientDetailProperties;
import xyz.molzhao.alink.properties.StorageClientProperties;
import xyz.molzhao.alink.service.IStorageService;
import xyz.molzhao.alink.utils.FileUtils;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @author Molzhao
 * @Description: AliyunOss服务类
 * @date 2022/2/20 15:25
 */
@Slf4j
@Service
public class AliyunOssService implements IStorageService {
    @Resource
    private StorageClientProperties storageClientProperties;

    @Override
    public String upload(StorageContext context) {
        if (null == context) {
            throw new BusinessException(ResultEnum.PARAM_ERROR);
        }

        if (null == context.getFile() && null == context.getInputStream()) {
            throw new BusinessException(ResultEnum.FILE_NOT_EXISTS);
        }

        if (CharSequenceUtil.isEmpty(context.getDirectory())) {
            throw new BusinessException(ResultEnum.DIRECTORY_NOT_EXISTS);
        }

        if (null != context.getFile()) {
            checkSize(Collections.singletonList(context.getFile()));
        }

        // 获取客户端配置类
        StorageClientDetailProperties storageClientDetailProperties = storageClientProperties.getConfig().get(StorageClientEnum.ALI_YUN_OSS.getDescription());

        //文件存储路径
        String filePath = FileUtils.fillFileName(context);

        OSSClient ossClient = null;
        try (
                //上传文件
                InputStream inputStream = context.getFile() != null && context.getFile().getSize() > 0
                        ? context.getFile().getInputStream() : context.getInputStream()
        ) {
            ossClient = new OSSClient(storageClientDetailProperties.getEndpoint(), storageClientDetailProperties.getAccessKey(), storageClientDetailProperties.getAccessKeySecret());
            PutObjectRequest request = new PutObjectRequest(storageClientDetailProperties.getBucketName(), filePath, inputStream);
            if (FileUtils.notNeedDownload(filePath)) {
                fillImgPutObjectRequest(request);
            }
            ossClient.putObject(request);
        } catch (Exception e) {
            throw new BusinessException(ResultEnum.UPLOAD_FAILED);
        } finally {
            if (null != ossClient) {
                ossClient.shutdown();
            }
        }

        return String.format(storageClientDetailProperties.getEndpointUrlFormat(), context.isUseHttps() ? CommonConstant.HTTPS_PROTO : CommonConstant.HTTP_PROTO, storageClientDetailProperties.getBucketName(), filePath);
    }

    @Override
    public boolean checkFileExists(String filePath) {
        StorageClientDetailProperties storageClientDetailProperties = storageClientProperties.getConfig().get(StorageClientEnum.ALI_YUN_OSS.getDescription());
        boolean result = false;
        OSSClient ossClient = null;
        try {
            ossClient = new OSSClient(storageClientDetailProperties.getEndpoint(), storageClientDetailProperties.getAccessKey(), storageClientDetailProperties.getAccessKeySecret());
            if (ossClient.doesObjectExist(storageClientDetailProperties.getBucketName(), filePath)) {
                result = true;
            }
        } catch (Exception e) {
            log.error("oss文件检查出现异常", e);
        } finally {
            if (null != ossClient) {
                ossClient.shutdown();
            }
        }
        return result;
    }

    @Override
    public boolean delete(String filePath) {
        StorageClientDetailProperties storageClientDetailProperties = storageClientProperties.getConfig().get(StorageClientEnum.ALI_YUN_OSS.getDescription());
        OSSClient ossClient = null;
        try {
            ossClient = new OSSClient(storageClientDetailProperties.getEndpoint(), storageClientDetailProperties.getAccessKey(), storageClientDetailProperties.getAccessKeySecret());

            //如果文件存在，则删除文件
            if (ossClient.doesObjectExist(storageClientDetailProperties.getBucketName(), filePath)) {
                ossClient.deleteObject(storageClientDetailProperties.getBucketName(), filePath);
            }
        } catch (Exception e) {
            log.error("oss文件删除出现异常", e);
            return false;
        } finally {
            if (null != ossClient) {
                ossClient.shutdown();
            }
        }
        return true;
    }

    @Override
    public void checkSize(List<MultipartFile> multipartFileList) {
        if (!CollectionUtils.isEmpty(multipartFileList.stream().filter(fileItem -> fileItem.getSize() > storageClientProperties.getMaxUploadSize()).collect(Collectors.toList()))) {
            throw new BusinessException(ResultEnum.UPLOAD_OVER_MAX_SIZE);
        }
    }

    private static PutObjectRequest fillImgPutObjectRequest(PutObjectRequest request) {
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
        metadata.setObjectAcl(CannedAccessControlList.PublicRead);
        metadata.setContentType("image/jpg");
        request.setMetadata(metadata);
        return request;
    }
}
